#include"tcpServer.h"
#include"msg.h"

#include"logger.h"
#include"ipAddressPort.h"

#include<sys/socket.h>  // socket
#include<netinet/in.h>  // sockaddr_in
#include<arpa/inet.h>   // inet_addr htons inet_ntop
#include<unistd.h>      // close

#include<cstring>
TcpServer::TcpServer(const IpAddressPort& ipAddressPort)
{
    m_lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == m_lfd)LOG_FATAL << strerror(errno);

    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;
    /* 主机字节序 -> 网络字节序 */
    ser_addr.sin_addr.s_addr = inet_addr(ipAddressPort.GetIpAddress().c_str());
    ser_addr.sin_port = htons(ipAddressPort.GetPort());
    if(-1 == bind(m_lfd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)))LOG_FATAL << strerror(errno);
    if(-1 == listen(m_lfd, 5))LOG_FATAL << strerror(errno);

}
TcpServer::~TcpServer()
{
    if(-1 == close(m_lfd))LOG_FATAL << strerror(errno);
}
int TcpServer::Accept()
{
    struct sockaddr_in cli;
    socklen_t socklen = sizeof(cli);
    int cfd = accept(m_lfd, (struct sockaddr*)&cli, &socklen);
    if(-1 == cfd)
    {
        LOG_ERROR << strerror(errno);
    }
    else
    {
        /* 输出客户端的信息 */
        char clientIpBuf[SMALL_BUF_LEN] = {0};
        /* ntop : cli.sin_addr -> char* -> clientIpBuf */
        if(NULL == inet_ntop(AF_INET, &cli.sin_addr, clientIpBuf, SMALL_BUF_LEN))
        {
            LOG_ERROR << strerror(errno);
        }
        else
        {
            /* 网络字节序 -> 主机字节序 */
            std::string clientIp(clientIpBuf);
            unsigned short clientPort = ntohs(cli.sin_port);
            IpAddressPort ipAddressPort(clientIp, clientPort);
            LOG_INFO << ipAddressPort.ToString();
        }
    }
    return cfd;
}
int TcpServer::SendMsg(int cfd, const std::string& msg)
{
    int numOfSendByte = send(cfd, msg.c_str(), strlen(msg.c_str()), 0);
    if(-1 == numOfSendByte)LOG_ERROR << strerror(errno);
    return numOfSendByte;
}
Msg TcpServer::RecvMsg(int cfd)
{
    char buf[LARGE_BUF_LEN] = {0};
    int numOfRecvByte = recv(cfd, buf, LARGE_BUF_LEN, 0);
    if(-1 == numOfRecvByte)LOG_ERROR << strerror(errno);
    return Msg{buf, numOfRecvByte};
}
int TcpServer::GetLfd() const
{
    return m_lfd;
}
#define __TEST__
#ifdef __TEST__
int main()
{
    IpAddressPort ser("127.0.0.1", 5000);
    TcpServer server(ser);
    while(1)
    {
        int cfd = server.Accept();
        if(-1 == cfd)
        {
            continue;
        }
        Msg m = server.RecvMsg(cfd);
        LOG_INFO << m.ToString();
    }
    return 0;
}
#endif